package com.hll.dao;

import com.mchange.v2.c3p0.ComboPooledDataSource;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

/**
 * 公共数据库访问类
 *
 * @author: Mr.Hu
 * @create: 2021-03-07 12:33
 */
public class BaseDao {
  private static String url;
  private static String driver;
  private static String userName;
  private static String password;
  // 会自动加载 resources/c3p0-config.xml(default-config),所以jdbc-url,数据库用户名\密码都在那
  private static ComboPooledDataSource dataSource = new ComboPooledDataSource(); // 连接池

  /**
   * 返回数据库连接
   *
   * @return: db Connection
   */
  public static Connection getConnection() {
    Connection connection = null;
    try {
      connection = dataSource.getConnection(); // 连接池取
    } catch (SQLException e) {
      e.printStackTrace();
    }
    return connection;
  }

  /**
   * sql query
   *
   * @return: 查询结果集
   */
  public static ResultSet execute(
      // 最后一个是多参数,写成Object就可以接受几乎所有类型参数, 要放在最后一个位置！
      // 之前我是写 Object[] params, 都一样
      // connection(自己申请) statement rs 调用者声明,随后自行release
      Connection connection, String sql, PreparedStatement statement, Object... params)
      throws SQLException {
    statement = connection.prepareStatement(sql);
    for (int i = 0; i < params.length; i++) {
      // 我靠,差点忘了设置参数是从 1 开始的！！！
      statement.setObject(i + 1, params[i]); // 不需要精确类型
    }
    return statement.executeQuery();
  }

  /**
   * 增删改
   *
   * @return: 影响行数 int
   */
  public static int executeUpdate(
      Connection connection, String sql, PreparedStatement statement, Object... params)
      throws SQLException {
    statement = connection.prepareStatement(sql);
    for (int i = 0; i < params.length; i++) {
      statement.setObject(i + 1, params[i]); // 不需要精确类型
    }
    return statement.executeUpdate();
  }

  /**
   * 清理connection\statement\rs
   *
   * @return: 是否清理成功(bool)
   */
  public static boolean release(
      Connection connection, PreparedStatement statement, ResultSet resultSet) {
    /*好多博客/教程这一块写的不一样,我最终选择这一种写法*/
    boolean flag = true;
    if (connection != null) {
      try {
        connection.close();
      } catch (SQLException throwables) {
        throwables.printStackTrace();
        flag = false;
      }
    }
    if (statement != null) {
      try {
        statement.close();
      } catch (SQLException throwables) {
        throwables.printStackTrace();
        flag = false;
      }
    }
    if (resultSet != null) {
      try {
        resultSet.close();
      } catch (SQLException throwables) {
        throwables.printStackTrace();
        flag = false;
      }
    }
    return flag; // 只有全关闭才true
  }

  /*
  // 类加载时执行
  static {
    init(); // 我把代码写在方法里,好看一些
  }

  private static void init() {
    // 由于数据库配置都在c3p0那，所以没用
    */
  /* Properties properties = new Properties();
  // this.getClass() 不能用在static上下文下
  InputStream resourceAsStream =
      BaseDao.class.getClassLoader().getResourceAsStream("db.properties");
  try {
    // 加载resources/配置
    properties.load(resourceAsStream);
  } catch (IOException e) {
    e.printStackTrace();
  }

  driver = (String) properties.get("driver");
  url = (String) properties.get("url");
  userName = (String) properties.get("user");
  password = (String) properties.get("password");*/
  /*

    initConnectionPool();
  }

  // 初始化数据库连接池
  private static void initConnectionPool() {
    // 如果没有写 c3p0-config.xml,就要像下面这样初始化
    */
  /* try {
    dataSource = new ComboPooledDataSource();
     dataSource.setDriverClass(driver);
    dataSource.setJdbcUrl(url);
    dataSource.setUser(userName);
    dataSource.setPassword(password);
    // 初始化连接个数,即池大小
    dataSource.setInitialPoolSize(20);
    // 池最大连接数
    dataSource.setMaxPoolSize(40);
    // 连接对象不够时,再申请多少个
    dataSource.setAcquireIncrement(5);
  } catch (SQLException e) {
    e.printStackTrace();
  }*/
  /*
  }

  // 传统的获取数据库连接,如果用完后close,那么再次获取又要连接,极其繁琐
  public static Connection getConnection() {
    Connection connection = null;
    try {
      Class.forName(driver);
      connection = DriverManager.getConnection(url, userName, password);
    } catch (Exception e) {
      e.printStackTrace();
    }
    return connection;
  }*/
}
